package xworker.dataObject.data;

import org.xmeta.ActionContext;
import xworker.lang.executor.Executor;

import java.util.ArrayList;
import java.util.List;

/**
 * 简单的绑定工具，把一个源对象绑定到目标对象上，使用注册的绑定器。
 */
public class DataBinderManager {
    private static final String TAG = DataBinderManager.class.getName();

    private static final List<DataBinder> binders = new ArrayList<>();
    static{
        binders.add(new DefaultDataBinder());
    }

    public static void registDataBinder(DataBinder dataBinder){
        if(!binders.contains(dataBinder)){
            binders.add(dataBinder);
        }
    }

    public static void removeDataBinder(DataBinder dataBinder){
        binders.remove(dataBinder);
    }

    public static boolean bind(Object source, Object target, String params, ActionContext actionContext){
        for(DataBinder binder : binders){
            if(binder.bind(source, target, params, actionContext)){
                return true;
            }
        }

        return  false;
    }

    public static void bind(ActionContext actionContext, String bindScripts){
        if(bindScripts != null){
            int lineIndex = 0;
            for(String line : bindScripts.split("[\n]")){
                lineIndex++;
                line = line.trim();
                if(line.startsWith("//") || line.startsWith("#") || !line.contains(">")){
                    continue;
                }

                int index = line.indexOf(">");
                String var = line.substring(0, index).trim();
                String[] targets = line.substring(index + 1).split("[,]");
                Object obj = actionContext.get(var);
                if(obj != null){
                    for(String key : targets){
                        String params = null;
                        int offset = key.indexOf("?");
                        if(offset != -1){
                            params = key.substring(offset);
                            key = key.substring(0, offset);
                        }
                        key = key.trim();
                        Object target = actionContext.getObject(key);
                        if(target == null){
                            Executor.info(TAG, "line:" + lineIndex + " Can not bind, Target " + key + " is null, code=" + line);
                        }else{
                            if(!bind(obj, target, params, actionContext)){
                                Executor.info(TAG, "line:" + lineIndex + " Can not bind, no binder, " + var + " > " + key + ", code=" + line);
                            }
                        }
                    }
                }else{
                    Executor.info(TAG, "line:" + lineIndex + " Can not bind, " + var + " is null, code=" + line);
                }
            }
        }
    }

    public static void bind(StaticDataManager dataManager, ActionContext actionContext, String bindScripts){
        if(bindScripts != null){
            int lineIndex = 0;
            for(String line : bindScripts.split("[\n]")){
                lineIndex++;
                line = line.trim();
                if(line.startsWith("//") || line.startsWith("#") || !line.contains(">")){
                    continue;
                }

                int index = line.indexOf(">");
                String var = line.substring(0, index).trim();
                String[] targets = line.substring(index + 1).split("[,]");
                Object obj = dataManager.get(var);
                if(obj != null){
                    for(String key : targets){
                        String params = null;
                        int offset = key.indexOf("?");
                        if(offset != -1){
                            params = key.substring(offset);
                            key = key.substring(0, offset);
                        }
                        Object target = actionContext.getObject(key);
                        if(target == null){
                            Executor.info(TAG, "line:" + lineIndex + " Can not bind, Target " + key + " is null, code=" + line);
                        }else{
                            if(!bind(obj, target, params, actionContext)){
                                Executor.info(TAG, "line:" + lineIndex + " Can not bind, no binder, " + var + " > " + key + ", code=" + line);
                            }
                        }
                    }
                }else{
                    Executor.info(TAG, "line:" + lineIndex + " Can not bind, " + var + " is null, code=" + line);
                }
            }
        }
    }
}
